package de.ur.iw.wiki.gui;

import static de.ur.iw.wiki.WikiConfig.*;
import static de.ur.iw.wiki.gui.WikiGUIUtil.*;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.text.NumberFormat;
import java.util.HashMap;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import de.ur.iw.interfaces.OnSettingsChangedListener;
import de.ur.iw.interfaces.WeightInformer;
import de.ur.iw.wiki.weighters.WeightInfo;

public class WikiGUI extends JFrame implements WeightInformer{
	private static final long serialVersionUID = 5318410539201842977L;
	
	private static final int DEFAULT_WINDOW_HEIGHT = 640;
	private static final int DEFAULT_WINDOW_WIDTH = 480;
	private static final String WINDOW_NAME = "RandomWikiWalks";
	
	private WikiGUIActionListener listener;
	private JPanel mainPanel;
	private JTabbedPane tabPanel;
	private JTextArea console;
	private HashMap<String,JTextField> textFields;
	private WeightInfo info;
	private WikiWeighterWizard wizard = null;
	
	public WikiGUI(){
		super(WINDOW_NAME);
		setLookAndFeel();
		listener = new WikiGUIActionListener(this);
		textFields = new HashMap<String, JTextField>();
		info = new WeightInfo();

		setupFrame();
	}
	
	private void setLookAndFeel(){
		 try {
	            // Set System L&F
	        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	        //javax.swing.plaf.metal.MetalLookAndFeel
	        if(UIManager.getSystemLookAndFeelClassName().equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel")){
	        	UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
	        }
	    } 
	    catch (UnsupportedLookAndFeelException e) {
	       // handle exception
	    }
	    catch (ClassNotFoundException e) {
	       // handle exception
	    }
	    catch (InstantiationException e) {
	       // handle exception
	    }
	    catch (IllegalAccessException e) {
	       // handle exception
	    }
	}
	
	public void display(){
		setVisible(true);
	}
	
	public void log(String message){
		console.append("\n"+message);
		console.setCaretPosition(console.getDocument().getLength());
	}
	
	public void flushConsole(){
		console.setText("");
	}
	
	public void setEnabled(boolean value){
		Component[] components = getComponents();
		for(int i = 0; i < components.length;i++){
			components[i].setEnabled(value);
		}
		super.setEnabled(true);
	}
	
	private void setupFrame(){
		  setTitle(WINDOW_NAME);
	      setSize(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT);
	      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	      setLocationRelativeTo(null);
	      this.setResizable(false);
	      setVisible(false);
	      mainPanel = new JPanel();
	      
	      setupSettings();
		  setupStartButton();
		  setupConsole();
		  add(mainPanel);
	}
	
	private void setupSettings(){
		JPanel settingsPanel = new JPanel();
		tabPanel = new JTabbedPane();
		tabPanel.setPreferredSize(new Dimension(DEFAULT_WINDOW_WIDTH - 30, 320));
		
		setupDatabaseSettings();
		setupRandomwalkSettings();
		setupResultSettings();
		settingsPanel.add(tabPanel);
		mainPanel.add(settingsPanel);
	}
	
	private void setupDatabaseSettings(){
		JPanel databasePanel = new JPanel();
		databasePanel.setLayout(new BoxLayout(databasePanel, BoxLayout.X_AXIS));
		
		JPanel labelPanel = new JPanel();
		labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
		labelPanel.setPreferredSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 300));
		labelPanel.setAlignmentY(TOP_ALIGNMENT);
		labelPanel.setAlignmentX(RIGHT_ALIGNMENT);
		databasePanel.add(labelPanel);
		
		JPanel textPanel = new JPanel();
		textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS));
		textPanel.setPreferredSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 *5, 300));
		textPanel.setAlignmentY(TOP_ALIGNMENT);
		textPanel.setAlignmentX(LEFT_ALIGNMENT);
		databasePanel.add(textPanel);
		
		
		JLabel databaseLocationLabel = new JLabel();
		databaseLocationLabel.setText("Database Location: ");
		databaseLocationLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(databaseLocationLabel);
		
		JTextField databaseLocation = new JTextField();
		databaseLocation.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 * 5, 20));
		databaseLocation.setText(DEFAULT_DATABASE_LOCATION);
		databaseLocation.setActionCommand(DATABASE_LOCATION);
		textPanel.add(databaseLocation);
		databaseLocation.addActionListener(listener);
		textFields.put(DATABASE_LOCATION, databaseLocation);
		
		JLabel databaseNameLabel = new JLabel();
		databaseNameLabel.setText("Database Name: ");
		databaseNameLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(databaseNameLabel);
		
		JTextField databaseName = new JTextField();
		databaseName.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 * 5, 20));
		databaseName.setText(DEFAULT_DATABASE_NAME);
		databaseName.setActionCommand(DATABASE_NAME);
		databaseName.addActionListener(listener);
		textPanel.add(databaseName);
		textFields.put(DATABASE_NAME, databaseName);
		
		JLabel tablenameLabel = new JLabel();
		tablenameLabel.setText("Database Tablename: ");
		tablenameLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(tablenameLabel);
		
		JTextField tablename = new JTextField();
		tablename.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*5, 20));
		tablename.setText(DEFAULT_DATABASE_TABLENAME);
		tablename.setActionCommand(DATABASE_TABLENAME);
		textPanel.add(tablename);
		tablename.addActionListener(listener);
		textFields.put(DATABASE_TABLENAME, tablename);
		
		JLabel usernameLabel = new JLabel();
		usernameLabel.setText("Username: ");
		usernameLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(usernameLabel);
		
		JTextField username = new JTextField();
		username.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*5, 20));
		username.setText(DEFAULT_USERNAME);
		username.setActionCommand(DATABASE_USERNAME);
		textPanel.add(username);
		username.addActionListener(listener);
		textFields.put(DATABASE_USERNAME, username);
		
		
		JLabel passwordLabel = new JLabel();
		passwordLabel.setText("Password: ");
		passwordLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(passwordLabel);
		
		JPasswordField password = new JPasswordField();
		password.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*5, 20));
		password.setText(DEFAULT_PASSWORD);
		password.setActionCommand(DATABASE_PASSWORD);
		textPanel.add(password);
		password.addActionListener(listener);
		textFields.put(DATABASE_PASSWORD, password);
		
		tabPanel.addTab("Database", null, databasePanel);
	}
	
	private void setupRandomwalkSettings(){
		JPanel wikiPanel = new JPanel();
		wikiPanel.setLayout(new BoxLayout(wikiPanel, BoxLayout.Y_AXIS));
		
		JCheckBox files = new JCheckBox(LABEL_FILES);
		files.setToolTipText("Use Files during the Randomwalk");
		files.addItemListener(listener);
		wikiPanel.add(files);
		
		JCheckBox limitedToCategory = new JCheckBox(LABEL_LIMITED_TO_CATEGORYS);
		limitedToCategory.setToolTipText("Limit the search to Categories");
		limitedToCategory.addItemListener(listener);
		wikiPanel.add(limitedToCategory);
		
		JCheckBox preventLoops = new JCheckBox(LABEL_PREVENT_LOOPS);
		preventLoops.setToolTipText("Prevent Loops during the Randomwalk");
		preventLoops.addItemListener(listener);
		wikiPanel.add(preventLoops);
		
		JCheckBox deadEnd = new JCheckBox(LABEL_DEAD_END);
		deadEnd.setToolTipText("Stepping back after finding a Dead End");
		deadEnd.addItemListener(listener);
		wikiPanel.add(deadEnd);
		
		JPanel parentPanel = new JPanel();
		parentPanel.setLayout(new BoxLayout(parentPanel, BoxLayout.X_AXIS));
		wikiPanel.add(parentPanel);
		
		
		JPanel labelPanel = new JPanel();
		labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
		labelPanel.setPreferredSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8* 3, 100));
		labelPanel.setAlignmentY(BOTTOM_ALIGNMENT);
		labelPanel.setAlignmentX(RIGHT_ALIGNMENT);
		parentPanel.add(labelPanel);
		
		JPanel textPanel = new JPanel();
		textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS));
		textPanel.setPreferredSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 * 5, 100));
		textPanel.setAlignmentY(BOTTOM_ALIGNMENT);
		textPanel.setAlignmentX(LEFT_ALIGNMENT);
		parentPanel.add(textPanel);
		
		
		JLabel categorysChanceLabel = new JLabel();
		categorysChanceLabel.setText(LABEL_CATEGORIES);
		categorysChanceLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(categorysChanceLabel);
		
		JTextField categorysChance = new JFormattedTextField(NumberFormat.getInstance());
		categorysChance.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 * 5, 20));
		categorysChance.setActionCommand(LABEL_CATEGORIES);
		textPanel.add(categorysChance);
		categorysChance.setText(DEFAULT_CATEGORY_CHANCE);
		categorysChance.addActionListener(listener);
		textFields.put(LABEL_CATEGORIES, categorysChance);
		
		JLabel maxStepsLabel = new JLabel();
		maxStepsLabel.setText(LABEL_LIMIT_PATHS);
		maxStepsLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(maxStepsLabel);
		
		JTextField maxSteps = new JFormattedTextField(NumberFormat.getInstance());
		maxSteps.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 * 5, 20));
		textPanel.add(maxSteps);
		maxSteps.setText(DEFAULT_MAX_PATHS);
		maxSteps.setActionCommand(LABEL_LIMIT_PATHS);
		maxSteps.addActionListener(listener);
		textFields.put(LABEL_LIMIT_PATHS, maxSteps);
		
		JLabel startPageLabel = new JLabel();
		startPageLabel.setText(LABEL_START_PAGE);
		startPageLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(startPageLabel);
		
		JTextField startPage = new JTextField();
		startPage.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 * 5, 20));
		textPanel.add(startPage);
		startPage.setText(DEFAULT_START_PAGE);
		startPage.setActionCommand(LABEL_START_PAGE);
		startPage.addActionListener(listener);
		textFields.put(LABEL_START_PAGE, startPage);
		
		wikiPanel.add(Box.createRigidArea(new Dimension(0,20)));
		
		
		JButton wizardButton = new JButton();
		wizardButton.setText(BUTTON_WIZARD);
		wizardButton.setActionCommand(BUTTON_WIZARD);
		wizardButton.addActionListener(listener);
		wikiPanel.add(wizardButton);
		
		tabPanel.addTab("Randomwalk", null, wikiPanel);
	}
	
	private void setupResultSettings(){
		JPanel resultPanel = new JPanel();
		resultPanel.setLayout(new BoxLayout(resultPanel, BoxLayout.Y_AXIS));
		
		JPanel parentPanel = new JPanel();
		parentPanel.setLayout(new BoxLayout(parentPanel, BoxLayout.X_AXIS));
		resultPanel.add(parentPanel);
		
		JPanel labelPanel = new JPanel();
		labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.Y_AXIS));
		labelPanel.setPreferredSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 100));
		labelPanel.setAlignmentY(TOP_ALIGNMENT);
		labelPanel.setAlignmentX(RIGHT_ALIGNMENT);
		parentPanel.add(labelPanel);
		
		JPanel textPanel = new JPanel();
		textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS));
		textPanel.setPreferredSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 *5, 100));
		textPanel.setAlignmentY(TOP_ALIGNMENT);
		textPanel.setAlignmentX(LEFT_ALIGNMENT);
		parentPanel.add(textPanel);

		JLabel hostLabel = new JLabel();
		hostLabel.setText(LABEL_HOST_URL);
		hostLabel.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8*3, 20));
		labelPanel.add(hostLabel);
		
		JTextField host = new JTextField();
		host.setMaximumSize(new Dimension((DEFAULT_WINDOW_WIDTH - 60)/8 * 5, 20));
		host.setText(DEFAULT_HOST);
		host.setActionCommand(LABEL_HOST_URL);
		textPanel.add(host);
		host.addActionListener(listener);
		textFields.put(LABEL_HOST_URL, host);
		
		resultPanel.add(Box.createRigidArea(new Dimension(0,20)));
		
		JButton wizardButton = new JButton();
		wizardButton.setText(BUTTON_RESULTS);
		wizardButton.setActionCommand(BUTTON_RESULTS);
		wizardButton.addActionListener(listener);
		wizardButton.setAlignmentY(TOP_ALIGNMENT);
		resultPanel.add(wizardButton);
		
		
		tabPanel.addTab("Result", null, resultPanel);
	}
	
	private void setupStartButton(){
		JButton startButton = new JButton();
		startButton.setText("Start Randomwalk");
		startButton.setPreferredSize(new Dimension(DEFAULT_WINDOW_WIDTH - 30, 40));
		startButton.setActionCommand(BUTTON_RANDOMWALK);
		startButton.addActionListener(listener);
		
		mainPanel.add(startButton);
	}
	
	private void setupConsole(){
		console = new JTextArea();
		//console.setPreferredSize(new Dimension(DEFAULT_WINDOW_WIDTH - 30, 200));
		console.setEnabled(false);
		console.setForeground(Color.WHITE);
		console.setBackground(Color.BLACK);
		
        console.setColumns(40);
        console.setLineWrap(true);
        console.setRows(12);
        console.setWrapStyleWord(true);
		
		JScrollPane scrollPanel = new JScrollPane(console);
		mainPanel.add(scrollPanel);
	}
	
	public void setOnSettingsChangedListener(OnSettingsChangedListener listener){
		this.listener.setOnSettingsChangedListener(listener);
	}
	
	public void removeOnSettingsChangedListener(){
		this.listener.removeOnSettingsChangedListener();
	}
	
	public HashMap<String,JTextField> getTextFields(){
		return textFields;
	}

	@Override
	public WeightInfo getWeightInfo() {
		return info;
	}
	
	protected void startWizard(){
		wizard = new WikiWeighterWizard(this, info);
		wizard.display();
	}



}
